package com.project.common.core.utils.weChat;

import com.project.common.core.config.prop.PropAttributes;
import com.project.common.core.config.prop.PropConfig;
import com.project.common.core.utils.HttpUtil;
import com.project.common.core.utils.JacksonUtil;
import com.project.common.core.utils.SpringUtils;
import com.project.common.core.utils.exception.BASE_RESP_CODE_ENUM;
import com.project.common.core.utils.exception.BaseCustomException;
import com.project.common.core.utils.ip.IpUtils;
import com.project.common.core.utils.redis.RedisClient;
import com.project.common.core.utils.wx.WXPayXmlUtil;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * 微信支付工具类
 *
 * @author WYY
 * @date 2018/07/10
 */
public final class WeChatPayUtil {
    /**
     * 日志对象
     */
    private static final Logger log = LoggerFactory.getLogger(WeChatPayUtil.class);

    /**
     * Redis客户端
     */
    private static RedisClient REDIS_CLIENT = null;

    /**
     * 统一下单url
     */
    public static final String UNIFIEDORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";

    /**
     * 查询订单url
     */
    public static final String ORDER_QUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery";

    /**
     * 申请退款
     */
    public static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";

    /**
     * 退款查询
     */
    public static final String REFUND_QUERY_URL = "https://api.mch.weixin.qq.com/pay/refundquery";

    /**
     * 获取单例RedisClient客户端单例对象
     *
     * @return
     */
    private static RedisClient getRedisClient() {
        if (REDIS_CLIENT == null) {
            synchronized (WeChatPayUtil.class) {
                if (REDIS_CLIENT == null) {
                    REDIS_CLIENT = SpringUtils.getBean("redisClient", RedisClient.class);
                }
            }
        }
        return REDIS_CLIENT;
    }

    /**
     * 微信公众号统一下单API【公众号支付】
     *
     * @param orderNo   订单号
     * @param payAmount 支付金额
     * @param openId    支付会员OPNEID
     * @param notiyUrl  异步通知URRL
     * @param orderDesc 订单描述
     * @param attach    附加数据
     * @param request   请求Request对象
     * @return
     * @throws
     */
    public static Map<String, Object> unifiedOrderOfPublicNumber(String orderNo, BigDecimal payAmount, String openId,
                                                                 String notiyUrl, String orderDesc, String attach, HttpServletRequest request) {
        // 生成一个16位的字符串
        Map<String, String> map = new TreeMap<>();
        String nonceStr = RandomStringUtils.randomAlphanumeric(16);
        // appid
        map.put("appid", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_APPID));
        // 商户号
        map.put("mch_id", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MCHID));
        // 设备号
        map.put("device_info", "WEB");
        // 随机字符串
        map.put("nonce_str", nonceStr);
        // 商品描述
        map.put("body", StringUtils.abbreviate(orderDesc.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5 ]", ""), 32));
        // 商品详情
        map.put("detail", StringUtils.abbreviate(orderDesc.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5 ]", ""), 8192));
        // 附加数据作为自定义参数使用
        if (StringUtils.isNotBlank(attach)) {
            map.put("attach", attach);
        }
        // 商户订单号
        map.put("out_trade_no", orderNo);
        // 货比类型
        map.put("fee_type", "CNY");
        // 总金额
        map.put("total_fee", String.valueOf(payAmount.multiply(new BigDecimal(100)).longValue()));
        // 终端ip
        map.put("spbill_create_ip", IpUtils.getIpAddr(request));
        // 通知地址
        map.put("notify_url", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_DOMAIN) + notiyUrl);
        // 交易类型
        map.put("trade_type", "JSAPI");
        map.put("openid", openId);

        //获下单ID标识【prepay_id】
        map.put("sign", WeChatSignUtil.generateMd5SignByKey(map, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_KEY)));
        String postStr = null;
        try {
            postStr = WXPayXmlUtil.mapToXml(map);
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            e.printStackTrace();
        }

        //第一次签名返回结果map
        String result = HttpUtil.httpsPost(WeChatPayUtil.UNIFIEDORDER_URL, postStr);
        log.info("\r\n **************** 预下单返回结果:{} **************** \r\n", result);
        Map<String, String> resMap = null;
        try {
            resMap = WXPayXmlUtil.xmlToMap(result);
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            e.printStackTrace();
        }

        // 签名失败微信直接返回FAIL
        if ("FAIL".equals(resMap.get("return_code"))) {
            throw new BaseCustomException("getPrepayIdReturnError", resMap.get("return_msg"));
        }

        // 验证签名
        if (!WeChatSignUtil.getCheckSign(resMap)) {
            throw new BaseCustomException("illegalSign", "签名错误");
        }

        // 返回结果失败
        if ("FAIL".equals(resMap.get("result_code"))) {
            throw new BaseCustomException("getPrepayIdResultError", resMap.get("err_code") + ":" + "err_code_des");
        }

        //生成微信支付签名
        String timestamp = Long.valueOf(System.currentTimeMillis() / 1000).toString();
        map.clear();//清空map
        map.put("appId", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_APPID));
        map.put("timeStamp", timestamp);
        map.put("nonceStr", nonceStr);
        map.put("package", "prepay_id=" + resMap.get("prepay_id"));
        map.put("signType", "MD5");
        String paySign = WeChatSignUtil.generateMd5SignByKey(map, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_KEY));
        log.debug("\r\n **************** 微信支付签名:{} **************** \r\n", paySign.toString());

        //返回结果
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("paySign", paySign);
        resultMap.put("appId", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_APPID));
        resultMap.put("timeStamp", timestamp);
        resultMap.put("nonceStr", nonceStr);
        resultMap.put("signType", "MD5");
        resultMap.put("out_trade_no", orderNo);
        resultMap.put("package", "prepay_id=" + resMap.get("prepay_id"));
        return resultMap;
    }

    /**
     * 微信公众号统一下单API【扫码支付】
     *
     * @param orderNo   订单号
     * @param payAmount 支付金额
     * @param notiyUrl  异步通知URRL
     * @param orderDesc 订单描述
     * @param request   请求Request对象
     * @return
     * @throws
     */
    public static Map<String, Object> unifiedOrderOfScan(String orderNo, BigDecimal payAmount, String notiyUrl, String orderDesc, HttpServletRequest request) throws Exception {
        // 初始化签名集合
        Map<String, String> map = new TreeMap<>();
        // appid
        map.put("appid", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_APPID));
        // 商户号
        map.put("mch_id", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MCHID));
        // 设备号
        map.put("device_info", "WEB");
        // 随机字符串
        String nonceStr = RandomStringUtils.randomAlphanumeric(16);
        map.put("nonce_str", nonceStr);
        // 商品描述
        map.put("body", StringUtils.abbreviate(orderDesc.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5 ]", ""), 32));
        // 商品详情
        map.put("detail", StringUtils.abbreviate(orderDesc.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5 ]", ""), 8192));
        // 商户订单号
        map.put("out_trade_no", orderNo);
        // 货比类型
        map.put("fee_type", "CNY");
        // 总金额
        map.put("total_fee", String.valueOf(payAmount.multiply(new BigDecimal(100)).longValue()));
        // 终端ip
        map.put("spbill_create_ip", IpUtils.getIpAddr(request));
        // 通知地址
        map.put("notify_url", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_SCAN_DOMAIN) + notiyUrl);
        // 交易类型
        map.put("trade_type", "NATIVE");
        // 产品ID【值为订单号】
        map.put("product_id", orderNo);

        // 调用扫码支付统一下单
        map.put("sign", WeChatSignUtil.generateMd5SignByKey(map, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_KEY)));
        String postStr = WXPayXmlUtil.mapToXml(map);
        String result = HttpUtil.httpsPost(WeChatPayUtil.UNIFIEDORDER_URL, postStr);
        log.info("\r\n **************** 扫码支付统一下单:{} **************** \r\n", result);
        Map<String, String> resMap = WXPayXmlUtil.xmlToMap(result);

        // 交易通信是否成功
        if ("FAIL".equals(resMap.get("return_code"))) {
            throw new BaseCustomException("扫码支付调用通信失败", resMap.get("return_msg"));
        }

        // 验证签名
        if (!WeChatSignUtil.getCheckSign(resMap)) {
            throw new BaseCustomException("扫码支付API响应验签错误", "签名错误");
        }

        // 业务结果返回是否成功
        if ("FAIL".equals(resMap.get("result_code"))) {
            throw new BaseCustomException("扫码支付业务失败", resMap.get("err_code") + ":" + "err_code_des");
        }

        // 返回结果
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("trade_type", resMap.get("trade_type"));
        resultMap.put("prepay_id", resMap.get("prepay_id"));
        resultMap.put("code_url", resMap.get("code_url"));

        return resultMap;
    }

    /**
     * 微信公众号统一下单API【H5支付】
     *
     * @param orderNo   订单号
     * @param payAmount 支付金额
     * @param notiyUrl  异步通知URL
     * @param orderDesc 订单描述
     * @param request   请求Request对象
     * @return
     * @throws
     */
    public static Map<String, Object> unifiedOrderOfH5(String orderNo, BigDecimal payAmount, String notiyUrl, String orderDesc, HttpServletRequest request) throws Exception {
        log.debug("\r\n **************** 预下单订单号:{} **************** \r\n", orderNo);
        // 初始化H5签名集合
        Map<String, String> map = new TreeMap<>();
        // 公众号AppId
        map.put("appid", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_APPID));
        // 商户号
        map.put("mch_id", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MCHID));
        // 随机字符串
        String nonceStr = RandomStringUtils.randomAlphanumeric(16);
        map.put("nonce_str", nonceStr);
        // 商品描述
        map.put("body", StringUtils.abbreviate(orderDesc.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5 ]", ""), 32));
        // 商户订单号
        map.put("out_trade_no", orderNo);
        // 货比类型
        map.put("fee_type", "CNY");
        // 总金额
        map.put("total_fee", String.valueOf(payAmount.multiply(new BigDecimal(100)).longValue()));
        // 终端ip
        map.put("spbill_create_ip", IpUtils.getIpAddr(request));
        // 通知地址
        map.put("notify_url", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_H5_DOMAIN) + notiyUrl);
        // 交易类型
        map.put("trade_type", "MWEB");
        // 设置场景值
        Map<Object, Object> sceneMap = new HashMap<>();
        Map<Object, Object> sceneInfoMap = new HashMap<>();
        sceneInfoMap.put("type", "Wap");
        sceneInfoMap.put("wap_url", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_H5_DOMAIN));
        sceneInfoMap.put("wap_name", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_H5_WAP_NAME));
        sceneMap.put("h5_info", sceneInfoMap);
        try {
            map.put("scene_info", JacksonUtil.toJsonStr(sceneMap));
        } catch (IOException e) {
            log.error("H5支付转化JSON出错");
            throw new BaseCustomException("unifiedOrderOfH5()", "H5支付转化JSON出错");
        }

        //获下单ID标识【prepay_id】
        map.put("sign", WeChatSignUtil.generateMd5SignByKey(map, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_KEY)));
        String postStr = WXPayXmlUtil.mapToXml(map);
        String result = HttpUtil.httpsPost(WeChatPayUtil.UNIFIEDORDER_URL, postStr);
        log.info("\r\n **************** H5统一下单返回:{} **************** \r\n", result);
        Map<String, String> resMap = WXPayXmlUtil.xmlToMap(result);

        // 签名失败微信直接返回FAIL
        if ("FAIL".equals(resMap.get("return_code"))) {
            throw new BaseCustomException("扫码支付调用通信失败", resMap.get("return_msg"));
        }

        // 验证签名
        if (!WeChatSignUtil.getCheckSign(resMap)) {
            throw new BaseCustomException("微信H5支付API响应验签错误", "签名错误");
        }

        // 返回结果失败
        if ("FAIL".equals(resMap.get("result_code"))) {
            throw new BaseCustomException("微信H5支付业务失败", resMap.get("err_code") + ":" + "err_code_des");
        }

        //返回结果
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("trade_type", resMap.get("trade_type"));
        resultMap.put("prepay_id", resMap.get("prepay_id"));
        resultMap.put("mweb_url", resMap.get("mweb_url"));

        return resultMap;
    }

    /**
     * 微信公众号支付退款申请
     *
     * @param orderNo        充值订单号
     * @param refundNo       商户退款单号
     * @param rechargeAmount 充值金额
     * @param refundAmount   退款金额
     * @return
     */
    public static Map<String, String> applyRefund(String orderNo, String refundNo, BigDecimal rechargeAmount, BigDecimal refundAmount) {
        log.info("\r\n ********************************* 申请退款接口调用开始 ************************************* \r\n");
        //初始化签名MAP
        Map<String, String> map = new TreeMap<String, String>();
        map.put("appid", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_APPID));
        map.put("mch_id", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MCHID));
        map.put("device_info", "WEB");
        String nonceStr = RandomStringUtils.randomAlphanumeric(16);
        map.put("nonce_str", nonceStr);
        map.put("out_trade_no", orderNo);
        map.put("out_refund_no", refundNo);
        map.put("total_fee", String.valueOf(rechargeAmount.multiply(new BigDecimal(100)).longValue()));
        map.put("refund_fee", String.valueOf(refundAmount.multiply(new BigDecimal(100)).longValue()));
        map.put("op_user_id", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MCHID));
        map.put("sign", WeChatSignUtil.generateMd5SignByKey(map, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_KEY)));

        //获取微信接口XML类型参数
        String postStr = null;
        try {
            postStr = WXPayXmlUtil.mapToXml(map);
        } catch (Exception e) {
            log.error("map转XML报错:{}", ExceptionUtils.getFullStackTrace(e));
        }

        //调用微信申请退款接口，并以MAP形式返回
        String result = HttpUtil.httpsPostWithCA(WeChatPayUtil.REFUND_URL, postStr, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_CERTDIR) + "/" + PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MCHID) + ".p12", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MCHID));
        Map<String, String> resultMap = null;
        try {
            resultMap = WXPayXmlUtil.xmlToMap(result);
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            e.printStackTrace();
        }

        //封装返回参数
        if (StringUtils.equals("FAIL", resultMap.get("return_code"))) {
            log.error("错误信息描述【" + resultMap.get("return_code") + "】:" + resultMap.get("return_msg"));
            throw new BaseCustomException(resultMap.get("return_code"), resultMap.get("return_msg"));
        }

        if (!WeChatSignUtil.getCheckSign(resultMap)) {
            throw new BaseCustomException("illegalSign", "签名错误");
        }
        log.info("\r\n ************************ 申请退款接口调用结束 *********************************** \r\n");
        return resultMap;
    }

    /**
     * 查询订单是否支付
     *
     * @param orderNo 订单号
     * @return
     */
    public static Map<String, String> queryOrderIsPay(String orderNo) {
        // 判断订单号是否为空
        if (StringUtils.isEmpty(orderNo)) {
            throw new BaseCustomException("orderSnEmpty", "订单号为空!");
        }

        // 初始化订单查询接口参数
        Map<String, String> map = new TreeMap<>();
        map.put("appid", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_APPID));
        map.put("mch_id", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MCHID));
        map.put("out_trade_no", orderNo);
        map.put("nonce_str", RandomStringUtils.randomAlphanumeric(32));
        map.put("sign", WeChatSignUtil.generateMd5SignByKey(map, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_KEY)));
        String xml = null;
        try {
            xml = WXPayXmlUtil.mapToXml(map);
        } catch (Exception e) {
            log.info("\r\n **************查询订单时XML解析错误:{}", ExceptionUtils.getFullStackTrace(e));
        }
        log.info("\r\n **************查询订单时提交的数据：{}", xml);

        // 调用查询API
        String result = HttpUtil.httpsPost(ORDER_QUERY_URL, xml);
        log.info("\r\n **************查询订单时获取到的数据：" + result);
        Map<String, String> resMap = null;
        try {
            resMap = WXPayXmlUtil.xmlToMap(result);
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            e.printStackTrace();
        }

        //获取结果时出现错误
        if (resMap == null || resMap.isEmpty()) {
            throw new BaseCustomException("【queryOrderIsPay】", "从微信查询订单信息失败");
        }

        //通信错误
        if (!StringUtils.equalsIgnoreCase(resMap.get("return_code"), "SUCCESS")) {
            throw new BaseCustomException("returnCodeError", resMap.get("return_msg"));
        }

        // 验证签名
        if (!WeChatSignUtil.getCheckSign(resMap)) {//验证签名
            throw new BaseCustomException("illegalSign", "签名错误");
        }

        //业务结果错误
        if (!StringUtils.equalsIgnoreCase(resMap.get("result_code"), "SUCCESS")) {
            throw new BaseCustomException("resultCodeError", resMap.get("err_code") + ":" + resMap.get("err_code_des"));
        }
        return resMap;
    }

    /**
     * 根据退款单号查询退款状态
     *
     * @param refundNo 商户退款单号
     * @return
     * @throws
     */
    public static Map<String, String> queryRefund(String refundNo) throws Exception {
        // 初始化签名参数
        Map<String, String> map = new TreeMap<>();
        String nonceStr = RandomStringUtils.randomAlphanumeric(16);
        map.put("appid", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_APPID));
        map.put("mch_id", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MCHID));
        map.put("device_info", "WEB");
        map.put("nonce_str", nonceStr);
        map.put("out_refund_no", refundNo);

        // 获取请求签名
        String signByKey = WeChatSignUtil.generateMd5SignByKey(map, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_KEY));
        map.put("sign", signByKey);

        // 初始化退单查询参数
        String postStr = WXPayXmlUtil.mapToXml(map);

        // 获取查询结果
        String result = HttpUtil.httpsPost(WeChatPayUtil.REFUND_QUERY_URL, postStr);
        Map<String, String> resMap = WXPayXmlUtil.xmlToMap(result);

        // 查询结果判断
        if (resMap == null) {
            throw new BaseCustomException(BASE_RESP_CODE_ENUM.SERVER_ERROR.getCode(), "微信退款查询通讯返回结果为null");
        }
        if ("FAIL".equals(resMap.get("return_code"))) {
            log.error("\r\n **********result_code失败{}:{}", resMap.get("return_code"), resMap.get("return_msg"));
            throw new BaseCustomException("getPrepayIdReturnError", resMap.get("return_msg"));
        }

        // 返回结果签名验证
        if (!WeChatSignUtil.getCheckSign(resMap)) {
            throw new BaseCustomException("illegalSign", "签名错误");
        }
        if ("FAIL".equals(resMap.get("result_code"))) {
            log.error("\r\n *************result_code失败：{}:{}", resMap.get("err_code"), resMap.get("err_code_des"));
            throw new BaseCustomException("getPrepayIdResultError", resMap.get("err_code") + ":" + resMap.get("err_code_des"));
        }
        return resMap;
    }

    /**
     * 微信小程序统一下单API【微信小程序】
     *
     * @param orderNo   订单号
     * @param payAmount 支付金额
     * @param openId    支付会员OPNEID
     * @param notifyUrl 异步通知URL
     * @param orderDesc 订单描述
     * @param request   请求Request对象
     * @return
     */
    public static Map<String, Object> unifiedOrderOfWxMini(String orderNo, BigDecimal payAmount, String openId, String notifyUrl, String orderDesc, HttpServletRequest request) {
        //生成一个16位的字符串
        Map<String, String> map = new TreeMap<>();
        String nonceStr = RandomStringUtils.randomAlphanumeric(16);
        //appid
        map.put("appid", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MINI_APPID));
        //商户号
        map.put("mch_id", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MINI_MCHID));
        //随机字符串
        map.put("nonce_str", nonceStr);
        //商品描述
        map.put("body", StringUtils.abbreviate(orderDesc.replaceAll("[^0-9a-zA-Z\\u4e00-\\u9fa5 ]", ""), 32));
        //商户订单号
        map.put("out_trade_no", orderNo);
        //货比类型
        map.put("fee_type", "CNY");
        //总金额
        map.put("total_fee", String.valueOf(payAmount.multiply(new BigDecimal(100)).longValue()));
        //终端ip
        map.put("spbill_create_ip", IpUtils.getIpAddr(request));
        //通知地址
        map.put("notify_url", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MINI_DOMAIN) + notifyUrl);
        //交易类型
        map.put("trade_type", "JSAPI");
        map.put("openid", openId);

        //获下单ID标识【prepay_id】
        map.put("sign", WeChatSignUtil.generateMd5SignByKey(map, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MINI_KEY)));
        String postStr = null;
        try {
            postStr = WXPayXmlUtil.mapToXml(map);
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            e.printStackTrace();
        }

        // 统一下单支付调用
        String result = HttpUtil.httpsPost(WeChatPayUtil.UNIFIEDORDER_URL, postStr);
        log.info("\r\n **************** 预下单返回结果:{} **************** \r\n", result);
        Map<String, String> resMap = null;
        try {
            resMap = WXPayXmlUtil.xmlToMap(result);
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            e.printStackTrace();
        }

        // 签名失败微信直接返回FAIL
        if ("FAIL".equals(resMap.get("return_code"))) {
            throw new BaseCustomException("getPrepayIdReturnError", resMap.get("return_msg"));
        }

        // 验证签名
        if (!WeChatSignUtil.getCheckSign(resMap)) {
            throw new BaseCustomException("illegalSign", "签名错误");
        }

        // 返回结果失败
        if ("FAIL".equals(resMap.get("result_code"))) {
            throw new BaseCustomException("getPrepayIdResultError", resMap.get("err_code") + ":" + "err_code_des");
        }

        //生成微信支付签名
        String timestamp = Long.valueOf(System.currentTimeMillis() / 1000).toString();
        map.clear();//清空map
        map.put("appId", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MINI_APPID));
        map.put("timeStamp", timestamp);
        map.put("nonceStr", nonceStr);
        map.put("package", "prepay_id=" + resMap.get("prepay_id"));
        map.put("signType", "MD5");
        String paySign = WeChatSignUtil.generateMd5SignByKey(map, PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MINI_KEY));
        log.debug("\r\n **************** 微信支付签名:{} **************** \r\n", paySign.toString());

        //返回结果
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("paySign", paySign);
        resultMap.put("appId", PropConfig.getProperty(PropAttributes.THIRDPARTY_WX_MINI_APPID));
        resultMap.put("timeStamp", timestamp);
        resultMap.put("nonceStr", nonceStr);
        resultMap.put("signType", "MD5");
        resultMap.put("out_trade_no", orderNo);
        resultMap.put("package", "prepay_id=" + resMap.get("prepay_id"));
        return resultMap;
    }

}
